會寫這篇文章的主要原因,是因為原始的文章是大陸人撰寫的文章,所以會有非常多的大陸用語,不是很喜歡看到大陸的用語,因此打算盡量都使用台灣的用語,使用正體中文再重新翻譯過一遍,以方便使用肉眼閱讀,這樣下次再重新閱讀的時候,就不用再重新轉換一遍詞彙的意思了XD,特此撰寫本篇文章作為紀錄以方便後續複查,雖然後面沒有機會再用到,但也算是個不錯的經驗。
作為一個完整的軟體,日誌是必不可少的。
程序從開發、測試、維護、運行等環節,都需要向控制台或文件等地方輸出大量訊息。
這些訊息的輸出,在很多時候是使用 System.out.println()
無法完成的。
日誌訊息根據用途與記錄內容的不同,可分為:調試日誌、運行日誌、異常日誌等。
Log4j
的全稱為 Log for java
,即專門用於 Java
語言的日誌記錄工具。
為了方便對於日誌資料訊息的輸出及顯示,對日誌內容進行了分級管理。日誌級別由高到低,共分 6 個級別:
無論是將日誌輸出到控制台,還是文件,其輸出都會降低程式的執行效率。
但由於調試、運行維護的需要,客戶的要求等原因,需要進行必要的日誌輸出。
這時候就必須要在程式碼中加入日誌輸出語句。
這些輸出語句若在程序運行時全部執行,則勢必會降低程式的執行效率。
例如,使用 System.out.println()
將訊息輸出到控制台,則所有的該輸出語句均將被執行。會大大降低程式的執行效率。
而要使其不輸出,唯一的辦法就是將這些輸出語句逐個全部刪除。
這是個費時費力的過程。
將日誌訊息進行分級管理,便可方便的控制訊息輸出內容及輸出位置:
哪些訊息需要輸出,哪些訊息不需要輸出,只需要在一個日誌輸出控制文件中稍加修改即可。
而程式碼中的輸出語句不用做任何修改。
從這個角度來說,程式碼中的日誌編寫,其實就是寫大量的輸出語句。
只不過,這些輸出語句比較特殊,它們具有級別,在程序運行期間不一定被執行。
它們的執行是由另一個控制文件控制。
Log4j 的日誌輸出控制文件,主要由三個部分構成:
有了日誌輸出控制文件,程式碼中只要設置好日誌訊息內容及其級別即可,通過控制文件便可控制這些日誌訊息的輸出了。
日誌屬性文件 log4j.properties
是專門用於控制日誌輸出的。其主要進行三方面控制:
日誌屬性文件由兩個對象組成:日誌附加器與根日誌。
根日誌,即為 Java 代碼中的日誌記錄器,其主要由兩個屬性構成:日誌輸出級別與日誌附加器。
日誌附加器,則由日誌輸出位置定義,由其它很多屬性進行修飾,如輸出佈局、文件位置、文件大小等。
所謂日誌附加器,就是為日誌記錄器附加上很多其它設置訊息。附加器的本質是一個接口,其定義語法為:log4j.appender.appenderName
= 輸出位置
org.apache.log4j.ConsoleAppender
:日誌輸出到控制台org.apache.log4j.FileAppender
:日誌輸出到文件org.apache.log4j.RollingFileAppender
:當日誌文件大小到達指定尺寸的時候將產生一個新的日誌文件org.apache.log4j.DailyRollingFileAppender
:每天產生一個日誌文件org.apache.log4j.HTMLLayout
:網頁佈局,以 HTML 表格形式佈局org.apache.log4j.SimpleLayout
:簡單佈局,包含日誌訊息的級別和訊息字符串org.apache.log4j.PatternLayout
:匹配器佈局,可以靈活地指定佈局模式。其主要是通過設置 PatternLayout 的 ConversionPattern 屬性值來控制具體輸出格式的 。打印參數: Log4J 採用類似 C 語言中的 printf 函數的打印格式格式化日誌訊息
%m
:輸出代碼中指定的消息%p
:輸出優先級,即 DEBUG
,INFO
,WARN
,ERROR
,FATAL
%r
:輸出自應用啟動到輸出該 log 訊息耗費的毫秒數%c
:輸出所屬的類目,通常就是所在類的全名%t
:輸出產生該日誌事件的線程名%n
:輸出一個回車換行符,Windows 平台為 /r/n
,Unix 平台為 /n
%d
:輸出日誌時間點的日期或時間,默認格式為ISO8601,也可以在其後指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS}
,輸出類似:2002年10月18日22:10:28,921
Testlog4.main(TestLog4.java: 10 )
slf4j 的全稱是 Simple Loging Facade For Java
,即它僅僅是一個為 Java 程序提供日誌輸出的統一接口,並不是一個具體的日誌實現方案,就比如 JDBC 一樣,只是一種規則而已。所以單獨的 slf4j 是不能工作的,必須搭配其他具體的日誌實現方案,比如 apache 的 org.apache.log4j.Logger
,JDK 自帶的 java.util.logging.Logger
以及 log4j
等。
參考原本的文章做修改後如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>idv.ete</groupId>
<artifactId>log4jTest</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>log4jTest</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin> <!--plugins要写在build标签下,不然无法识别 -->
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version> <!--maven-compiler-plugin版本写一个中央仓库有的版本,保存后它会自动下载 -->
<configuration>
<source>10</source> <!--我的jdk是10.0.1的,写成10.0.1不好用,所以就写成10了 -->
<target>10</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
log4j.properties
配置文件注意:檔案名字要是 log4j.properties 要一模一樣。
在 src/main/resources
目錄下創建名為 log4j.properties
的屬性配置文件
log4j.rootLogger=INFO, console, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=logs/log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.MaxFileSize=1024KB
log4j.appender.A3.MaxBackupIndex=10
log4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n
日誌配置相關說明:
log4j.rootLogger
:根日誌,配置了日誌級別為 INFO
,預定義了名稱為 console
、file
兩種附加器log4j.appender.console
:console 附加器,日誌輸出位置在控制台log4j.appender.console.layout
:console 附加器,採用匹配器佈局模式log4j.appender.console.layout.ConversionPattern
:console 附加器,日誌輸出格式為:日期 日誌級別 [類名] - 消息換行符
log4j.appender.file
:file 附加器,每天產生一個日誌文件log4j.appender.file.File
:file 附加器,日誌文件輸出位置 logs/log.log
log4j.appender.file.layout
:file 附加器,採用匹配器佈局模式log4j.appender.A3.MaxFileSize
:日誌文件最大值log4j.appender.A3.MaxBackupIndex
:最多紀錄文件數log4j.appender.file.layout.ConversionPattern
:file 附加器,日誌輸出格式為:日期 日誌級別 [類名] - 消息換行符
創建一個測試類別,並測試日誌輸出效果,參考原本文章的程式碼修改後如下:
package idv.ete;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class App
{
public static final Logger logger = LoggerFactory.getLogger(App.class);
public static void main( String[] args )
{
System.out.println( "Hello World!" );
logger.info("slf4j for info");
logger.debug("slf4j for debug");
logger.error("slf4j for error");
logger.warn("slf4j for warn");
String message = "Hello SLF4J";
logger.info("slf4j message is : {}", message);
}
}
執行後 Console 顯示如下:
項目根目錄下也會多出 logs/log.log
目錄及文件